// #include "Register.h"
// package com.wish.jniProtocal;

#include "DataBean.h"
#include "Register.h"
#include "LogUtil.h"
#include <stdio.h>
#include <stdlib.h>

#define NELEM(x) ((int)(sizeof(x) / sizeof((x)[0])))

data_bean_block m_data_bean_block;

int find_class(JNIEnv *env, const char *name, jclass *clazz_out)
{
    jclass clazz = (*env)->FindClass(env, name);
    if (clazz == NULL)
    {
        LOGE("Can't find %s", name);
        return -1;
    }
    *clazz_out = (jclass)(*env)->NewGlobalRef(env, clazz); // 这里必须新建一个全局的引用
    return 0;
}

int get_field(JNIEnv *env, jclass *clazz, const char *name, const char *sig, jfieldID *field_out)
{
    jfieldID filed = (*env)->GetFieldID(env, *clazz, name, sig);
    if (filed == NULL)
    {
        LOGE("Can't find. filed name: %s, sig: %s", name, sig);
        return -1;
    }
    *field_out = filed;
    return 0;
}

void register_data_bean_class(JNIEnv *env)
{

    int ret = find_class(env, "com/wish/jni/DataBean", &m_data_bean_block.clazz);
    if (ret != 0)
    {
        LOGE("register_data_bean_class  failed");
        return;
    }
    jclass clazz = m_data_bean_block.clazz;
    // 构造方法
    m_data_bean_block.constructor = (*env)->GetMethodID(env, clazz, "<init>", "()V");
    get_field(env, &clazz, "mRtFlag", "B", &m_data_bean_block.rtFlag);
    get_field(env, &clazz, "mVersion", "I", &m_data_bean_block.version);
    get_field(env, &clazz, "mPkLen", "I", &m_data_bean_block.pkLen);
    get_field(env, &clazz, "mPkId", "I", &m_data_bean_block.pkId);
    get_field(env, &clazz, "mPkCmd", "B", &m_data_bean_block.pkCmd);
    get_field(env, &clazz, "mPkAck", "B", &m_data_bean_block.pkAck);
    get_field(env, &clazz, "mParaCnt", "I", &m_data_bean_block.paraCnt);
    get_field(env, &clazz, "mOl", "[C", &m_data_bean_block.ol);
    get_field(env, &clazz, "mOid", "[C", &m_data_bean_block.oid);
    get_field(env, &clazz, "mVal", "[I", &m_data_bean_block.val);
    get_field(env, &clazz, "mStartPoint", "I", &m_data_bean_block.startPoint);
    get_field(env, &clazz, "mStopPoint", "I", &m_data_bean_block.stopPoint);
    get_field(env, &clazz, "mReportArrayVal", "[I", &m_data_bean_block.reportArrayVal);
    get_field(env, &clazz, "mFormPkArray", "[B", &m_data_bean_block.formPkArray);

    LOGD("register_data_bean_class  OK!");
}

void register_classes(JNIEnv *env)
{
    register_data_bean_class(env);
}

jobject data_bean_c_to_java(JNIEnv *env, jni_data_bean *c_data_bean)
{
    if (c_data_bean == NULL)
    {
        LOGW("input data is null!");
        return NULL;
    }
    LOGD("start data_bean_c_to_java");
    jobject java_data_bean = (*env)->NewObject(env, m_data_bean_block.clazz, m_data_bean_block.constructor);

    (*env)->SetByteField(env, java_data_bean, m_data_bean_block.rtFlag, c_data_bean->rtFlag);
    (*env)->SetIntField(env, java_data_bean, m_data_bean_block.version, c_data_bean->version);
    (*env)->SetIntField(env, java_data_bean, m_data_bean_block.pkLen, c_data_bean->pkLen);
    (*env)->SetIntField(env, java_data_bean, m_data_bean_block.pkId, c_data_bean->pkId);
    (*env)->SetByteField(env, java_data_bean, m_data_bean_block.pkCmd, c_data_bean->pkCmd);
    (*env)->SetIntField(env, java_data_bean, m_data_bean_block.paraCnt, c_data_bean->paraCnt);
    (*env)->SetByteField(env, java_data_bean, m_data_bean_block.pkAck, c_data_bean->pkAck);
    (*env)->SetIntField(env, java_data_bean, m_data_bean_block.startPoint, c_data_bean->startPoint);
    (*env)->SetIntField(env, java_data_bean, m_data_bean_block.stopPoint, c_data_bean->stopPoint);

    // int  array
    jsize valLen = NELEM(c_data_bean->val);
    // LOGD("val array len: %d", valLen);
    jintArray val32 = (*env)->NewIntArray(env, valLen);
    (*env)->SetIntArrayRegion(env, val32, 0, valLen, c_data_bean->val);
    (*env)->SetObjectField(env, java_data_bean, m_data_bean_block.val, val32);

    jsize oidLen = NELEM(c_data_bean->oid);
    // LOGD("oid array len: %d", oidLen);
    jcharArray oidArray = (*env)->NewCharArray(env, oidLen);
    (*env)->SetCharArrayRegion(env, oidArray, 0, oidLen, c_data_bean->oid);
    (*env)->SetObjectField(env, java_data_bean, m_data_bean_block.oid, oidArray);

    LOGD("oidArray[0]: %x", c_data_bean->oid[0]);

    jsize olLen = NELEM(c_data_bean->ol);
    // LOGD("ol array len: %d", olLen);
    jcharArray olArray = (*env)->NewCharArray(env, olLen);
    (*env)->SetCharArrayRegion(env, olArray, 0, olLen, c_data_bean->ol);
    (*env)->SetObjectField(env, java_data_bean, m_data_bean_block.ol, olArray);

    // jsize reportArrayValLen = NELEM(c_data_bean->reportArrayVal);
    // jcharArray reportArrayVal = (*env)->NewCharArray(env, reportArrayValLen);
    // (*env)->SetCharArrayRegion(env, reportArrayVal, 0, reportArrayValLen, c_data_bean->reportArrayVal);
    // (*env)->SetObjectField(env, java_data_bean, m_data_bean_block.reportArrayVal, reportArrayVal);

    jsize reportArrayValLen = NELEM(c_data_bean->reportArrayVal);
    jintArray reportArrayVal = (*env)->NewIntArray(env, reportArrayValLen);
    (*env)->SetIntArrayRegion(env, reportArrayVal, 0, reportArrayValLen, c_data_bean->reportArrayVal);
    (*env)->SetObjectField(env, java_data_bean, m_data_bean_block.reportArrayVal, reportArrayVal);

    jsize formPkArrayLen = NELEM(c_data_bean->formPkArray);
    // LOGD("formPkArrayLen array len: %d", formPkArrayLen);
    jbyteArray formPkArray = (*env)->NewByteArray(env, formPkArrayLen);
    (*env)->SetByteArrayRegion(env, formPkArray, 0, formPkArrayLen, c_data_bean->formPkArray);
    (*env)->SetObjectField(env, java_data_bean, m_data_bean_block.formPkArray, formPkArray);

    return java_data_bean;
}

void data_bean_java_to_c(JNIEnv *env, jobject jData_bean_in, jni_data_bean *cData_beanOut)
{
    LOGD("start data_bean_java_to_c");
    if (jData_bean_in == NULL)
    {
        LOGW("jData_bean_in data is null!");
        return;
    }

    // cData_beanOut->version = (*env)->GetIntField(env, jData_bean_in, m_data_bean_block.version);
    cData_beanOut->version = (*env)->GetIntField(env, jData_bean_in, m_data_bean_block.version);
    cData_beanOut->pkLen = (*env)->GetIntField(env, jData_bean_in, m_data_bean_block.pkLen);
    cData_beanOut->pkId = (*env)->GetIntField(env, jData_bean_in, m_data_bean_block.pkId);
    cData_beanOut->paraCnt = (*env)->GetIntField(env, jData_bean_in, m_data_bean_block.paraCnt);
    cData_beanOut->pkCmd = (*env)->GetByteField(env, jData_bean_in, m_data_bean_block.pkCmd);
    cData_beanOut->pkAck = (*env)->GetByteField(env, jData_bean_in, m_data_bean_block.pkAck);
    cData_beanOut->startPoint = (*env)->GetIntField(env, jData_bean_in, m_data_bean_block.startPoint);
    cData_beanOut->stopPoint = (*env)->GetIntField(env, jData_bean_in, m_data_bean_block.stopPoint);
    // byte array
    jbyteArray formPkArray = (jbyteArray)(*env)->GetObjectField(env, jData_bean_in, m_data_bean_block.formPkArray);
    jbyte *byteData = (*env)->GetByteArrayElements(env, formPkArray, 0);
    int len = (*env)->GetArrayLength(env, formPkArray);
    // LOGD("formPkArray byte array len: %d", len);
    memcpy(cData_beanOut->formPkArray, byteData, len * sizeof(jbyte));
    (*env)->ReleaseByteArrayElements(env, formPkArray, byteData, 0);
    // char array
    jcharArray olArray = (jcharArray)(*env)->GetObjectField(env, jData_bean_in, m_data_bean_block.ol);
    jchar *olData = (*env)->GetCharArrayElements(env, olArray, 0);
    len = (*env)->GetArrayLength(env, olArray);
    //  LOGD("olData char array len: %d", len);
    memcpy(cData_beanOut->ol, olData, len * sizeof(jchar));
    (*env)->ReleaseCharArrayElements(env, olArray, olData, 0);
    jcharArray oidArray = (jcharArray)(*env)->GetObjectField(env, jData_bean_in, m_data_bean_block.oid);
    jchar *oidData = (*env)->GetCharArrayElements(env, oidArray, 0);
    len = (*env)->GetArrayLength(env, oidArray);
    // LOGD("oidArray char array len: %d", len);
    memcpy(cData_beanOut->oid, oidData, len * sizeof(jchar));
    (*env)->ReleaseCharArrayElements(env, oidArray, oidData, 0);

    jintArray reportArrayVal = (jintArray)(*env)->GetObjectField(env, jData_bean_in, m_data_bean_block.reportArrayVal);
    jint *reportArrayValData = (*env)->GetIntArrayElements(env, reportArrayVal, 0);
    len = (*env)->GetArrayLength(env, reportArrayVal);
    memcpy(cData_beanOut->reportArrayVal, reportArrayValData, len * sizeof(jint));
    (*env)->ReleaseIntArrayElements(env, reportArrayVal, reportArrayValData, 0);

    jintArray oidVal = (jintArray)(*env)->GetObjectField(env, jData_bean_in, m_data_bean_block.val);
    jint *oidValData = (*env)->GetIntArrayElements(env, oidVal, 0);
    len = (*env)->GetArrayLength(env, oidVal);
    // LOGD("oidVal int array len: %d", len);
    memcpy(cData_beanOut->val, oidValData, len * sizeof(jint));
    (*env)->ReleaseIntArrayElements(env, oidVal, oidValData, 0);
    // LOGD("end data_bean_java_to_c");
}

void updateFormPk_c_to_java(JNIEnv *env, jobject jData_bean, jni_data_bean *cData_bean)
{
    jsize formPkArrayLen = NELEM(cData_bean->formPkArray);
    jbyteArray formPkArray = (*env)->NewByteArray(env, formPkArrayLen);
    (*env)->SetByteArrayRegion(env, formPkArray, 0, formPkArrayLen, cData_bean->formPkArray);
    (*env)->SetObjectField(env, jData_bean, m_data_bean_block.formPkArray, formPkArray);


      (*env)->SetIntField(env, jData_bean, m_data_bean_block.pkLen, cData_bean->pkLen);


}